package com.qianli.cashmama.product.server.controller.pay;

import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.fqgj.log.factory.LogFactory;
import com.fqgj.log.interfaces.Log;
import com.google.common.collect.Maps;
import com.jsoniter.JsonIterator;
import com.jsoniter.any.Any;
import com.jsoniter.output.JsonStream;
import com.qianli.cashmama.product.server.dao.PayCallbackLogDao;
import com.qianli.cashmama.product.server.dao.PayRequestLogDao;
import com.qianli.cashmama.product.server.entity.ClReceiverDetailEntity;
import com.qianli.cashmama.product.server.entity.PayCallbackLogEntity;
import com.qianli.cashmama.product.server.entity.PayRequestLogEntity;
import com.qianli.cashmama.product.server.job.PayCallBackToBizJob;
import com.qianli.cashmama.product.server.job.SendToMerchantData;
import com.robert.vesta.util.IdUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.security.MessageDigest;
import java.util.*;

/**
 * Created with IntelliJ IDEA.
 * User: sm
 * Date: 2021/12/6
 * Time: 11:00 上午
 */

@RestController
public class PayController {
    private static final Log LOGGER = LogFactory.getLog(PayController.class);

    @NacosValue(value = "${kd.pay.merchantId:0}", autoRefreshed = true)
    private String kdPayMerchantId;

    @NacosValue(value = "${kd.pay.type:0}", autoRefreshed = true)
    private String kdPayType;

    @NacosValue(value = "${kd.pay.productId:0}", autoRefreshed = true)
    private String productId;

    @NacosValue(value = "${kd.pay.notifyUrl:0}", autoRefreshed = true)
    private String notifyUrl;
    @NacosValue(value = "${kd.pay.key:0}", autoRefreshed = true)
    private String kdPayKey;

    @NacosValue(value = "${kd.pay.url:http://glob-pay.com/api/pay/create_order}", autoRefreshed = true)
    private String kdPayUrl;


    @Autowired
    private PayRequestLogDao payRequestLogDao;

    @Autowired
    private PayCallbackLogDao payCallbackLogDao;

    @Autowired
    private PayCallBackToBizJob payCallBackToBizJob;

    @RequestMapping("/gupta.deal.contract")
    public OpenApiResponse mock1() {
        LOGGER.info("== 访问合同接口 ==");
        return new OpenApiResponse(400, "mock");
    }

    @RequestMapping("/firstPush")
    public OpenApiResponse f() {
        LOGGER.info("== firstPush ==");
        return new OpenApiResponse(200, "mock");
    }

    @RequestMapping("/secondPush")
    public OpenApiResponse s() {
        LOGGER.info("== secondPush ==");
        return new OpenApiResponse(200, "mock");
    }

    @RequestMapping("/thirdPush")
    public OpenApiResponse t() {
        LOGGER.info("== thirdPush ==");
        return new OpenApiResponse(200, "mock");
    }

    @RequestMapping("/cashbar/order/pay/url")
    public OpenApiResponse mock2(@RequestBody SendToMerchantData request) {
        LOGGER.info("== 请求支付链接 ==,request1:{}", JSON.toJSON(request));
        String bizData = request.getBizData();
        if (StringUtils.isEmpty(bizData)) {
            return new OpenApiResponse(400, "start repayment exception2");
        }
        RepayRequest deserialize1 = JsonIterator.deserialize(bizData, RepayRequest.class);

        Any deserialize = JsonIterator.deserialize(deserialize1.getExtraInfo());
        String userName = "default";
        ClReceiverDetailEntity clReceiverDetailEntity = payCallbackLogDao.getOneByMobile(deserialize.get("tel").toString());
        if (clReceiverDetailEntity != null) {
            userName = clReceiverDetailEntity.getName();
        }
        String orderNoFor3d = IdUtils.genId() + "";
        PayRequestLogEntity payRequestLogEntity = new PayRequestLogEntity()
                .setTradeNo(deserialize1.getOrderNo())
                .setOrderNo(orderNoFor3d)
                .setOrderAmount(new BigDecimal(deserialize.get("orderAmount").toString()))
                .setTel(deserialize.get("tel").toString())
                .setUserName(userName);

        payRequestLogDao.insert(payRequestLogEntity);
        PayRequestLogEntity payRequestLogEntity1 = payRequestLogDao.selectByTripleOrderNo(orderNoFor3d);

        Map headers = Maps.newHashMap();
        headers.put("Content-Type", "application/x-www-form-urlencoded");
        Map<String, String> params = Maps.newHashMap();
        params.put("type", kdPayType);
        params.put("mchId", kdPayMerchantId);
        params.put("productId", productId);
        params.put("notifyUrl", notifyUrl);
        params.put("mchOrderNo", orderNoFor3d);
        params.put("orderAmount", "" + payRequestLogEntity.getOrderAmount().multiply(new BigDecimal("100")).longValue());
        params.put("clientIp", "127.0.0.1");
        params.put("device", "android");
        params.put("uid", payRequestLogEntity1.getId() + "");
        params.put("customerName", payRequestLogEntity.getUserName());
//        params.put("tel", request.getTel());
        String mobile = payRequestLogEntity.getTel();
        params.put("tel", "91" + mobile.substring(0, 4) + "***" + mobile.substring(7));
        params.put("email", "no-reply@gmail.com");
        params.put("returnType", "json");

        LOGGER.info("== 请求的参数 == request:{}", JsonStream.serialize(params));
        try {
            String sign = generateSignature(params, kdPayKey);
            params.put("sign", sign);

            LOGGER.info("== 请求支付链接 sign ==,request2:{}", JSON.toJSON(params));
        } catch (Exception e) {
            LOGGER.error("== 请求支付链接 sign 异常==", e);
            return new OpenApiResponse(400, "start repayment exception");
        }

        String result = HttpUtil.postPage(kdPayUrl, params, headers);
        LOGGER.info("== 访问支付链接接口 ==,res:{}", result);
        KdPayRequestResponse kdPayRequestResponse = JSON.parseObject(result, KdPayRequestResponse.class);

        payRequestLogEntity1.setCode(kdPayRequestResponse.getCode())
                .setMessage(kdPayRequestResponse.getMessage());
        if ("200".equals(kdPayRequestResponse.getCode())) {
            payRequestLogEntity1.setPayOrderId(kdPayRequestResponse.getData().getPayOrderId())
                    .setPayUrl(kdPayRequestResponse.getData().getPayUrl());

            payRequestLogDao.updateByPrimaryKey(payRequestLogEntity1);
            PayUrlResponse payUrlResponse = new PayUrlResponse()
                    .setJumpUrl(kdPayRequestResponse.getData().getPayUrl());
            return new OpenApiResponse(200, "success").setData(payUrlResponse);
        }


        return new OpenApiResponse(400, "create repayment link failed");
    }


    @RequestMapping("/gupta.payment.confirm")
    public OpenApiResponse mock3() {
        LOGGER.info("== 访问提现接口 ==");
        return new OpenApiResponse(400, "mock");
    }

    @RequestMapping("/checkUser")
    public OpenApiResponse mock4() {
        LOGGER.info("== 访问用户是否可用接口 ==");
        return new OpenApiResponse(200, "mock");
    }

    @RequestMapping("/pay/callback")
    public String payCallBack(KdPayCallBackRequest request) {

        try {
            PayCallbackLogEntity payCallbackLogEntity = new PayCallbackLogEntity()
                    .setCode(request.getCode().intValue())
                    .setMchId(request.getMchId()+"")
                    .setTradeNo(request.getMchOrderNo())
                    .setProductId(request.getProductId().intValue())
                    .setOrderAmount(new BigDecimal(request.getOrderAmount()))
                    .setPayOrderId(request.getPayOrderId())
                    .setPaySuccessTime(request.getPaySuccessTime())
                    .setMessage(request.getMessage())
                    .setExtra(request.getExtra());

            payCallbackLogDao.insert(payCallbackLogEntity);
            LOGGER.info("== payCallBack ==");
        } catch (Exception e) {
            LOGGER.error("== payCallBack ==", e);
            return "failed";
        }
        return "success";
    }

    @RequestMapping("/gupta.loan.amount")
    public OpenApiResponse mock5() {
        LOGGER.info("== 访问阶段金额接口 ==");
        return new OpenApiResponse(400, "mock");
    }

    @RequestMapping("/api.repayment.result")
    public OpenApiResult repaymentStatus(@RequestBody ReceiveData receiveData) {
        if (receiveData == null || com.fqgj.common.utils.StringUtils.isEmpty(receiveData.getMerchantCode()) || com.fqgj.common.utils.StringUtils.isEmpty(receiveData.getSign()) || com.fqgj.common.utils.StringUtils.isEmpty(receiveData.getBizData())) {
            return OpenApiResult.failure(OpenApiResultCode.FAILURE, "params invalid");
        }

        LOGGER.info("== 还款回调 ==,data:{}", JsonStream.serialize(receiveData));

        return OpenApiResult.success();
    }


    @RequestMapping("/test2")
    public String repaymentCallBackToBizTest() {

        LOGGER.info("== 推送到业务系统回调 测试==");
        payCallBackToBizJob.tellDc();
        return "repayment-test";
    }


    public static void main(String[] args) {

        String s1 = new BigDecimal("200.00").multiply(new BigDecimal("100")).toString();
//        String s = Long.valueOf().toString();
        long l = new BigDecimal("200.00").multiply(new BigDecimal("100")).longValue();
        String aa = l + "";
        System.err.println(11);

    }

//    public static void main(String[] args) {
//        Map headers = Maps.newHashMap();
//        headers.put("Content-Type", "application/x-www-form-urlencoded");
//        Map<String, String> params = Maps.newHashMap();
//        params.put("mchId", "1128");
//        params.put("type", "0");
//        params.put("mchOrderNo", "18768389141510072711TD");
//        params.put("productId", "21");
//        params.put("orderAmount", "300000");
//        params.put("notifyUrl", "http://147.139.37.96:9101/pay/callback");
//        params.put("clientIp", "127.0.0.1");
//        params.put("device", "android");
//        params.put("uid", "100001");
//        params.put("customerName", "jeff");
//        params.put("tel", "919210011001");
//        params.put("email", "zhangs@gmail.com");
//        params.put("returnType", "json");
//
//        try {
//            String sign = generateSignature(params, "6bb4d2df6ef742faa2f5a5e2f7f7ae45");
//            params.put("sign", sign);
//
//            System.err.println(11);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//
//
//        String result = HttpUtil.postPage("http://glob-pay.com/api/pay/create_order", params, headers);
//        KdPayRequestResponse kdPayRequestResponse = JSON.parseObject(result, KdPayRequestResponse.class);
//        System.err.println(result);
//
//    }

    public static String generateSignature(final Map<String, String> data, String key) throws Exception {
        Set<String> keySet = data.keySet();
        String[] keyArray = keySet.toArray(new String[keySet.size()]);
        Arrays.sort(keyArray);
        StringBuilder sb = new StringBuilder();
        for (String k : keyArray) {
            sb.append(k).append("=").append(data.get(k)).append("&");
        }
        sb.append("key=").append(key);
        return MD5(sb.toString());

    }


    public static String MD5(String data) throws Exception {
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] array = md.digest(data.getBytes("UTF-8"));
        StringBuilder sb = new StringBuilder();
        for (byte item : array) {
            sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
        }
        return sb.toString();
    }


    /**
     * 以form表单形式提交数据，发送post请求
     *
     * @param url       请求地址
     * @param paramsMap 具体数据
     * @return 服务器返回数据
     * @explain 1.请求头：httppost.setHeader("Content-Type","application/x-www-form-urlencoded")
     * 2.提交的数据格式：key1=value1&key2=value2...
     */
    public static String httpPostWithForm(String url, Map<String, String> paramsMap) {
        // 用于接收返回的结果
        String resultData = "";
        try {
            HttpPost post = new HttpPost(url);
            List<BasicNameValuePair> pairList = new ArrayList<BasicNameValuePair>();
            // 迭代Map-->取出key,value放到BasicNameValuePair对象中-->添加到list中
            for (String key : paramsMap.keySet()) {
                pairList.add(new BasicNameValuePair(key, paramsMap.get(key)));
            }
            UrlEncodedFormEntity uefe = new UrlEncodedFormEntity(pairList, "utf-8");
            post.setEntity(uefe);
            // 创建一个http客户端
            CloseableHttpClient httpClient = HttpClientBuilder.create().build();
            // 发送post请求
            HttpResponse response = httpClient.execute(post);

            // 状态码为：200
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                // 返回数据：
                resultData = EntityUtils.toString(response.getEntity(), "UTF-8");
            } else {
                throw new RuntimeException("接口连接失败！");
            }
        } catch (Exception e) {
            throw new RuntimeException("接口连接失败！");
        }
        return resultData;
    }

}
